﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using DC2010;
using DC2010.Objects.Base;
using DC2010.Objects.Structures;
using log4net;
using log4net.Config;
using DC2010.Objects.Data;
using DC2012.Render;

namespace Xna
{
    public class Neocortex
    {
        public static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        public string DataDirectory = "Data";
        public WallPoints WallPoints { get; set; }

        //private Dictionary<string, DCAnimatedSprite> dctAnimatedSprite { get; set; }

        
        private static Neocortex _i;
        private Neocortex()
        {
            WallPoints = new WallPoints();
        }

        public void Ini()
        {
            //dctAnimatedSprite = new Dictionary<string, DCAnimatedSprite>();

            log.Info("Neocortex, Processing animations");
            WallPoints = new WallPoints();
            // initialize animations...
            // root have to be initialized at this moment);
            //foreach (ItemGfx ei in Root.I.ItemSystem.DictGfx.Values)
            //{
            //    AddGfx(ei, ei.Id);
            //    //AddSprite(ei.Icon.IsAnimated, ei.Icon.TileWidth, ei.Icon.TileHeight, (int)ei.Icon.Delay, ei.Id+"_ICON", ei.Icon.Normal);
            //}

            //foreach (SpriteInfo ei in Root.I.SpriteSystem.DictInfo.Values)
            //{
            //    AddSprite(ei.IsAnimated, ei.TileWidth, ei.TileHeight, (int)ei.Delay, ei.Id, ei.Path);
            //}
        }

        ///// <summary>
        ///// Add sprite to collection. Duplication is checked
        ///// </summary>
        ///// <param name="isAnimated">Is this sprite animated?</param>
        ///// <param name="tileWidth">Width of sprite (auto for non animated ones)</param>
        ///// <param name="tileHeight">Height of sprite (auto for non animated ones)</param>
        ///// <param name="delay">Delay between frames</param>
        ///// <param name="id">Is of sprite</param>
        ///// <param name="path">Path to file</param>
        ///// <returns>Added animated sprite</returns>
        //private DCAnimatedSprite AddSprite(bool isAnimated, int tileWidth, int tileHeight, int delay, string id, string path)
        //{
        //    // Create collection for animations
        //    AnimationCollection ac = new AnimationCollection();
        //    ac.Add(Path.Combine(Environment.CurrentDirectory, Path.Combine(DataDirectory, path)), new Size(tileWidth, tileHeight));
        //    ac.Delay = delay;

        //    // Create our animated sprite and set properties
        //    DCAnimatedSprite ans = new DCAnimatedSprite();
        //    ans.Animations.Add("default", ac);
        //    ans.CurrentAnimation = "default";
        //    ans.Animate = isAnimated; //in case of static image...do not animate
        //    ans.Frame = 1;
        //    ans.Anim_Path = path;
        //    ans.Anim_TileWidth = tileWidth;
        //    ans.Anim_TileHeight = tileHeight;
        //    ans.Anim_Delay = delay;
        //    ans.Anim_IsAnimated = isAnimated;
        //    ans.Id = id;
        //    dctAnimatedSprite.Add(id, ans);
        //    log.InfoFormat("Neocortex, Sprite {0} added", id);

        //    return ans;
        //}

        //public DCAnimatedSprite CreateNewSprite(DCAnimatedSprite dcas, string id)
        //{
        //    AnimationCollection ac = new AnimationCollection();
        //    ac.Add(Path.Combine(Environment.CurrentDirectory, Path.Combine(DataDirectory, dcas.Anim_Path)), new Size(dcas.Anim_TileWidth, dcas.Anim_TileHeight));
        //    ac.Delay = dcas.Anim_Delay;

        //    // Create our animated sprite and set properties
        //    DCAnimatedSprite ans = new DCAnimatedSprite();
        //    ans.Animations.Add("default", ac);
        //    ans.CurrentAnimation = "default";
        //    ans.Animate = dcas.Anim_IsAnimated; 
        //    ans.Frame = dcas.Frame;
        //    ans.Anim_Path = dcas.Anim_Path;
        //    ans.Anim_TileWidth = dcas.Anim_TileWidth;
        //    ans.Anim_TileHeight = dcas.Anim_TileHeight;
        //    ans.Anim_Delay = dcas.Anim_Delay;
        //    ans.Anim_IsAnimated = dcas.Anim_IsAnimated;
        //    ans.Id = id;
        //    ans.TileType = dcas.TileType;
        //    if (!dctAnimatedSprite.ContainsKey(id))
        //    {
        //        dctAnimatedSprite.Add(id, ans);
        //        log.InfoFormat("Neocortex, Sprite {0} added", id);
        //    }

        //    return ans;
        //}

        //public DCAnimatedSprite CreateNewSprite(DCAnimatedSprite dcas, Surface s, string id, bool store)
        //{
        //    AnimationCollection ac = new AnimationCollection();
        //    ac.Add(s);
        //    ac.Delay = dcas.Anim_Delay;

        //    // Create our animated sprite and set properties
        //    DCAnimatedSprite ans = new DCAnimatedSprite();
        //    ans.Animations.Add("default", ac);
        //    ans.CurrentAnimation = "default";
        //    ans.Animate = dcas.Anim_IsAnimated;
        //    ans.Frame = dcas.Frame;
        //    ans.Anim_Path = dcas.Anim_Path;
        //    ans.Anim_TileWidth = dcas.Anim_TileWidth;
        //    ans.Anim_TileHeight = dcas.Anim_TileHeight;
        //    ans.Anim_Delay = dcas.Anim_Delay;
        //    ans.Anim_IsAnimated = dcas.Anim_IsAnimated;
        //    ans.Id = id;
        //    ans.TileType = dcas.TileType;
        //    if (!dctAnimatedSprite.ContainsKey(id))
        //    {
        //        if (store)
        //        {
        //            dctAnimatedSprite.Add(id, ans);
        //            log.InfoFormat("Neocortex, Sprite {0} added", id);
        //        }
        //    }

        //    return ans;
        //}

        //public DCAnimatedSprite CreateNewSprite(DCAnimatedSprite x)
        //{
        //    string s = Guid.NewGuid().ToString();
        //    return CreateNewSprite(x, s);
        //}

        /// <summary>
        /// Add all relevant Gfx for item, which can appear inside the dungeon
        /// </summary>
        /// <param name="bgf">Source object</param>
        /// <param name="code">What item code should I use.</param>
        public void AddGfx(BaseGfx bgf, string code)
        {
            code = code.Replace("_ICON", "");
            code = code.Replace("_AWAY", "");

            //AddSprite(bgf.Icon.IsAnimated, bgf.Icon.TileWidth, bgf.Icon.TileWidth, (int)bgf.Icon.Delay, code+"_ICON", bgf.Icon.Texture);
            //AddSprite(bgf.Away.IsAnimated, bgf.Away.TileWidth, bgf.Away.TileWidth, (int)bgf.Away.Delay, code + "_AWAY", bgf.Icon.Texture);
        }

        ///// <summary>
        ///// Try to retrieve animated sprite from collection
        ///// </summary>
        ///// <param name="code">Sprite id to retrieve</param>
        ///// <returns></returns>
        //public DCAnimatedSprite GetAnimatedSprite(string code)
        //{
        //    //when gfx will be clear from object gfx property. we must create intance for some gfx.
        //    //Every animated sprite has its own X and Y...
        //    if (dctAnimatedSprite.ContainsKey(code))
        //    {
        //        return dctAnimatedSprite[code];
        //    }

        //    //4c42687d-6fcd-4026-bb21-71662326e4fb_GFX_LANTERN_ICON
        //    //Sprite s = new Sprite();
        //    BaseGfx bgf = TryToGetGfx(code);

        //    if (bgf!=null)
        //    {
        //        AddGfx(bgf, code);
        //        return GetAnimatedSprite(code);
        //    }
        //    log.ErrorFormat("Problem while creating sprite: {0}", code);
        //    return null;
        //}

        ///// <summary>
        ///// Try to retrieve animated sprite from collection
        ///// </summary>
        ///// <param name="code">Sprite id to retrieve</param>
        ///// <returns></returns>
        //public DCAnimatedSprite GetAnimatedSprite_Simply(string code)
        //{
        //    //when gfx will be clear from object gfx property. we must create intance for some gfx.
        //    //Every animated sprite has its own X and Y...
        //    if (dctAnimatedSprite.ContainsKey(code))
        //    {
        //        return dctAnimatedSprite[code];
        //    }

        //    return null;
        //}

        //public List<DCAnimatedSprite> IntersectsWith(int X, int Y, SpriteCollection coll)
        //{
        //    List<DCAnimatedSprite> lstS = new List<DCAnimatedSprite>();
        //    foreach (DCAnimatedSprite sprite in coll)
        //    {
        //        bool b = sprite.IntersectsWith(new Point(X, Y));

        //        if (b)
        //            lstS.Add(sprite);
        //    }

        //    return lstS;
        //}

        ///// <summary>
        ///// Get part of animated sprite - one specific frame. Returns new instance.
        ///// </summary>
        ///// <param name="animatedSprite"></param>
        ///// <param name="frame"></param>
        ///// <returns></returns>
        //public DCAnimatedSprite GetSubFrame(string animatedSprite, string tileid, int frame)
        //{
        //    DCAnimatedSprite s = GetAnimatedSprite_Simply(animatedSprite);

        //    if (s != null)
        //    {
        //        DCAnimatedSprite sOld = GetAnimatedSprite_Simply(tileid);
        //        if (sOld != null) return sOld;

        //        //AnimatedSprite asa = new AnimatedSprite();
        //        DCAnimatedSprite dcs = CreateNewSprite(s, tileid);
        //        //DCAnimatedSprite dcs = new DCAnimatedSprite(s.a.Surface, s.Position);
        //        dcs.Animate = false;
        //        dcs.Frame = frame;
        //        dcs.Id = tileid;
        //        return dcs;
        //    }

        //    return null;
        //}

        //public DCAnimatedSprite GetScaledSprite(string animatedSprite, double zoom, int left)
        //{
        //    DCAnimatedSprite s = (DCAnimatedSprite)I.GetAnimatedSprite(animatedSprite);

        //    if (s != null)
        //    {
        //        DCAnimatedSprite sOld = GetAnimatedSprite_Simply(s.Id + "_ZOOM_" + zoom+"_"+left);
        //        if (sOld != null) return sOld;

        //        DCAnimatedSprite dcs = CreateNewSprite(s, s.Animations["default"][0].CreateScaledSurface(zoom) ,s.Id + "_ZOOM_" + zoom+"_"+left, true);
        //        //dcs.Animations["default"][0]..Surface = dcs.Animations["default"][0].CreateScaledSurface(zoom);
        //        //tile width a height???????????
        //        return dcs;
        //    }

        //    return null;
        //}

        //public DCAnimatedSprite GetFlippedSprite(DCAnimatedSprite s, int left)
        //{
        //    //DCAnimatedSprite s = I.GetAnimatedSprite(animatedSprite);

        //    if (s != null)
        //    {
        //        DCAnimatedSprite sOld = GetAnimatedSprite_Simply(s.Id + "_FLIPPED_" + left);
        //        if (sOld != null) return sOld;

        //        DCAnimatedSprite dcs = CreateNewSprite(s, s.Animations["default"][0].CreateFlippedHorizontalSurface(), s.Id + "_FLIPPED_" + left, true);
        //        dcs.X = s.X;
        //        dcs.Y = s.Y;

        //        return dcs;
        //    }

        //    return null;
        //}

        public BaseGfx TryToGetGfx(string code)
        {
            BaseGfx bgf = null;

            string[] field = code.Split('_');

            if (field.GetLength(0) >= 1)
            {
                //first is guid
                //last could be ICON...etc...
                string PlayWithThis = code.Replace(field[0] + "_", "");
                BaseGfx igfx = Root.I.ItemSystem.GetGfx(PlayWithThis);

                if (igfx == null)
                    igfx = Root.I.CreatureSystem.GetGfx(PlayWithThis);

                // ... do this for all systems...
                PlayWithThis = PlayWithThis.Replace("_" + field[field.GetLength(0) - 1], "");

                if (igfx == null)
                    igfx = Root.I.ItemSystem.GetGfx(PlayWithThis);

                if (igfx == null)
                    igfx = Root.I.CreatureSystem.GetGfx(PlayWithThis);

                bgf = igfx;

            }

            return bgf;
        }

        //public void Remove(DCAnimatedSprite dcs)
        //{
        //    //get key
        //    string key = (from i in dctAnimatedSprite
        //                  where i.Value.Id == dcs.Id
        //                  select i.Key).ToString();

        //    if (!string.IsNullOrEmpty(key))
        //    {
        //        dctAnimatedSprite.Remove(key);
        //    }
        //}

        public static Neocortex I
        {
            get
            {
                if (_i == null)
                {
                    //configure log4net
                    XmlConfigurator.Configure();

                    _i = new Neocortex();
                }
                return _i;
            }
        }


    }
}
